Skip to content

[3주차] 강지훈/[feat] User, Post, Comment, Report 도메인 API 구현#121

Open
theSnackOverflow wants to merge 7 commits intoLeets-Official:강지훈/mainfrom
theSnackOverflow:강지훈/3주차

Hidden character warning

The head ref may contain hidden characters: "\uac15\uc9c0\ud6c8/3\uc8fc\ucc28"
Open

[3주차] 강지훈/[feat] User, Post, Comment, Report 도메인 API 구현#121
theSnackOverflow wants to merge 7 commits intoLeets-Official:강지훈/mainfrom
theSnackOverflow:강지훈/3주차

Conversation

@theSnackOverflow
Copy link
Copy Markdown
Member

@theSnackOverflow theSnackOverflow commented Apr 7, 2026

1. 과제 요구사항 중 구현한 내용

  • 프로젝트 구조 구성 (도메인별 Controller/Service/Repository 레이어 분리)
  • RESTful API 설계 원칙 적용 (자원 중심 URL, HTTP 메서드로 동작 표현)
  • 요청 데이터 처리 (@RequestParam, @PathVariable, @RequestBody, @RequestHeader)
  • Entity/DTO 분리 및 공통 응답 포맷 (ApiResponse<T>) 적용
  • Bean Validation + 전역 예외처리 (GlobalExceptionHandler) 구현
  • Swagger UI (/swagger-ui.html) 연동

2. 핵심 변경 사항

패키지 구조 개편

  • 기존 평탄 구조(controller/, service/, dto/)를 도메인별 구조(domain/{user,post,comment,report}/)로 전환
  • 공통 모듈을 global/response/, global/exception/으로 분리

공통 인프라

  • global/response/ApiResponse<T>: 공통 응답 래퍼 (success, error 정적 팩토리)
  • global/exception/ErrorCode (enum): HTTP 상태 + 에러 코드 + 메시지 일원화
  • global/exception/GlobalExceptionHandler: BusinessException, Validation, TypeMismatch, MissingHeader, 500 안전망 핸들러 추가

도메인별 API (/api/v1/...)

  • User: POST /users, GET /users/{userId}, PATCH /users/{userId}, DELETE /users/{userId}
  • Post: POST /posts, GET /posts?status=&page=&size=, GET /posts/{postId}, PATCH /posts/{postId}, DELETE /posts/{postId}
  • Comment: POST /posts/{postId}/comments, GET /posts/{postId}/comments, PATCH /comments/{commentId}, DELETE /comments/{commentId}
  • Report: POST /reports, GET /reports

인증 처리: Spring Security 미도입 상태로 작성자 식별은 X-User-Id 헤더로 임시 처리

Jackson snake_case 전역 설정으로 응답 필드 자동 변환

3. 실행 및 검증 결과

로컬에서 H2 인메모리 DB 기반으로 동작 확인 (./gradlew bootRun)

사용자 생성 POST /api/v1/users

// 요청
{ "username": "테스트유저", "email": "test@test.com", "password": "pw1234" }

// 응답
{
  "status": "success",
  "message": "요청이 성공적으로 처리되었습니다.",
  "data": { "user_id": 1, "username": "테스트유저", "email": "test@test.com", "created_at": "..." }
}

게시글 작성 POST /api/v1/posts (X-User-Id: 1)

// 요청
{ "title": "첫 번째 게시글", "content": "내용입니다" }

// 응답
{ "status": "success", "data": { "post_id": 1, "status": "PUBLISHED", ... } }

댓글 + 대댓글 조회 GET /api/v1/posts/1/comments

{
  "data": [{
    "comment_id": 1, "content": "첫 댓글",
    "replies": [{ "comment_id": 2, "content": "대댓글", "parent_comment_id": 1 }]
  }]
}

권한 없는 게시글 수정 → 403

{ "status": "error", "message": "접근 권한이 없습니다." }

빈 제목으로 게시글 작성 → 400

{ "status": "error", "message": "제목은 필수입니다." }
스크린샷 2026-04-07 오후 11 40 59 스크린샷 2026-04-07 오후 11 41 06

4. 완료 사항

  1. 도메인 패키지 구조 전환 및 불필요한 더미 파일 제거
  2. 공통 응답/예외처리 모듈 (global/response, global/exception) 분리
  3. User/Post/Comment/Report 도메인 Repository, Service, Controller, DTO 구현
  4. 각 엔티티에 정적 팩토리 메서드 및 도메인 변경 메서드 추가 (Setter 미사용)
  5. Bean Validation + ErrorCode 기반 전역 예외처리 연동
  6. Jackson snake_case 전역 설정 및 Swagger UI 연동

5. 추가 사항

  • 인증/인가는 현재 X-User-Id 헤더 기반 임시 처리이며, Spring Security 도입 시 교체 예정
  • 신고(Report) 대상 구분은 target_type (POST/COMMENT) 필드로 처리
  • 대댓글은 1뎁스로 제한 (부모 댓글의 대댓글에는 답글 불가)

제출 체크리스트

  • PR 제목이 규칙에 맞다
  • base가 강지훈/main 브랜치다
  • compare가 강지훈/3주차 브랜치다
  • 프로젝트가 정상 실행된다
  • 본인을 Assignee로 지정했다
  • 파트 담당 Reviewer를 지정했다
  • 리뷰 피드백을 반영한 뒤 머지/PR close를 진행한다

- ApiResponse를 dto에서 global/response로 이동
- ErrorCode enum 기반 BusinessException 도입
- BusinessException, MissingRequestHeader, TypeMismatch 등 핸들러 추가
- User 엔티티에 정적 팩토리/update 메서드 추가
- UserRepository, UserService, UserController 작성
- 이메일 중복 검사, Bean Validation 적용
- Post 엔티티에 정적 팩토리/update 메서드 추가
- PostRepository, PostService, PostController 작성
- status/페이지네이션 필터, 작성자 권한 검증
- Comment 엔티티에 정적 팩토리/update 메서드 추가
- CommentRepository, CommentService, CommentController 작성
- 1뎁스 대댓글 제한, 작성자 권한 검증
- Report 엔티티에 정적 팩토리 메서드 추가
- ReportRepository, ReportService, ReportController 작성
- POST/COMMENT 대상 분기 처리 및 검증
@theSnackOverflow theSnackOverflow requested a review from a team April 7, 2026 14:39
@theSnackOverflow theSnackOverflow self-assigned this Apr 7, 2026
@theSnackOverflow theSnackOverflow added the enhancement New feature or request label Apr 7, 2026
@sky-0131
Copy link
Copy Markdown

sky-0131 commented Apr 9, 2026

유저 도메인을 구현한 점이 인상 깊었습니다! 이를 참고하여, 테스트를 간편하게 수행할 수 있었습니다. 기본에는 테스트를 위해 필요한 값을 DB에 넣고 시행했으나, 유저 ID를 연동한 포스트 기능을 실제 서비스를 진행하는 것처럼 테스트할 수 있었습니다.

@yukyoungs
Copy link
Copy Markdown

구조가 정말 탄탄하네요! user 관련 코드들부터 post 까지 세세하게 생성해주셨네요 배워갑니당 특히 전역 예외 처리와 ApiResponse 공통화가 인상 깊습니다. 몇 가지 사소한 피드백 남겨요!

@daekyochung
Copy link
Copy Markdown

Report 도메인을 추가로 구현하신 부분과 GlobalExceptionHandler로 일관된 예외 처리를 하시는 것이 인상깊습니다! Swagger UI 문서도 완벽하게 정리되어 있어 API 이해도가 높아졌습니다! 고생하셨습니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants